import { WebSocket, WebSocketServer } from 'ws';
import { OnModuleInit, Injectable, Inject } from '@nestjs/common';
import { LogService } from '../log/log.service';
import { timestamp } from 'rxjs';
import { NodeService } from '../node/node.service';
export class WebsocketGateway implements OnModuleInit {
  private wss: WebSocketServer;
  private clients: Set<WebSocket> = new Set();
  // 存储客户端心跳状态
  private heartbeatStatus: Map<WebSocket, { lastBeat: number }> = new Map();
  // 心跳检查间隔 (毫秒)
  private readonly HEARTBEAT_INTERVAL = 30000;
  // 心跳超时时间 (毫秒)
  private readonly HEARTBEAT_TIMEOUT = 60000;
  // 存储客户端订阅的日志信息
  private logSubscriptions: Map<WebSocket, { deploymentId: string, nodeId: string }[]> = new Map()
  constructor(private logService: LogService,private nodeService:NodeService) {}
  onModuleInit() {
    this.wss = new WebSocket.Server({ port: 9998});
    this.wss.on('connection', (ws: WebSocket) => {
      // 添加新连接的客户端
      this.clients.add(ws);
      // 初始化心跳状态
      this.heartbeatStatus.set(ws, { lastBeat: Date.now() });
      // 初始化日志订阅
      this.logSubscriptions.set(ws, []);
      console.log('Client connected');
      // 处理接收到的消息
      ws.on('message', (message: string) => {
        try {
          const data = JSON.parse(message.toString());
          // 更新心跳时间
          this.updateHeartbeat(ws);
          this.handleMessage(ws, data);
        } catch (error) {
          console.error('Error parsing message:', error);
        }
      });

      // 处理客户端断开连接
      ws.on('close', () => {
        this.clients.delete(ws);
        this.heartbeatStatus.delete(ws);
        this.logSubscriptions.delete(ws);
        console.log('Client disconnected');
      });
      // 开启定时器循环推送CPU和内存数据，保留整数
      const pushInterval = setInterval(() => {
        if (ws.readyState === WebSocket.OPEN) {
          ws.send(JSON.stringify({
            cmd: 'JRLC.total.cpu',
            data: {
              cpu: Math.floor(Math.random() * 100),
              meu: Math.floor(Math.random() * 100)
            }
          }));
        } else {
          // 如果连接已关闭，清除定时器
          clearInterval(pushInterval);
        }
      }, 3000); // 每3秒推送一次
      
      // 立即发送一次初始数据
      ws.send(JSON.stringify({
        cmd: 'JRLC.total.cpu',
        data: {
          cpu: Math.floor(Math.random() * 100),
          meu: Math.floor(Math.random() * 100)
        }
      }));
    });
    
  }

  private async handleMessage(client: WebSocket, data: any) {
      if(data.command === 'heartbeat'){
        this.updateHeartbeat(client);
        client.send(JSON.stringify({
          cmd: 'heartbeat',
          data: {
             cmd:"heartbeat",
          }
        }));
      }
  }

  // 向所有客户端广播日志更新，无需预先订阅
  public broadcastLogUpdate(deploymentId: string, nodeId: string, logLine: string): void {
    this.clients.forEach(client => {
      // 添加到订阅列表（如果尚未订阅）
      const subscriptions = this.logSubscriptions.get(client) || [];
      if (!subscriptions.some(sub => sub.deploymentId === deploymentId && sub.nodeId === nodeId)) {
        subscriptions.push({ deploymentId, nodeId });
        this.logSubscriptions.set(client, subscriptions);
      }     
      // 0-4随机数对应日志内容
      // const logs = ["JRLC.logs.app.success","JRLC.logs.app.failed","JRLC.logs.app.info","JRLC.logs.app.warning","JRLC.logs.app.error"]
      // 发送日志更新
      client.send(JSON.stringify({
        cmd: 'JRLC.logs.app',
        data: {
          timestamp:Date.now().toString(),
          logs: 'jrlc.logs.app',
          PID:2
        }
      }));
    });
  }


  // 更新客户端心跳时间
  private updateHeartbeat(client: WebSocket): void {
    const status = this.heartbeatStatus.get(client);
    if (status) {
      status.lastBeat = Date.now();
    }
  }

  // 根据ips创建状态并逐个更新推送
  public createStatus(ips: string[],cmd:string) {
    if (!ips || ips.length === 0) {   // 无IP时直接发送结束消息
      this.clients.forEach(client => {
        client.send(JSON.stringify({
          cmd: cmd,
          data: {
            status: "end"
          }
        }));
      });
      return;
    }
    // 初始化所有IP的状态
    const statusMap = {};
    ips.forEach(ip => {
      statusMap[ip] = {
        status: 'start',
        message: ""
      };
    });
    // 记录当前处理中的IP索引
    let currentIndex = 0;
    // 定义更新函数
    const updateNextIP = () => {
      // 获取当前需要更新的IP
      const currentIP = ips[currentIndex];
      // 根据索引判断成功或失败（单数成功，双数失败）
      const isSuccess = currentIndex % 2 !== 0; // 单数为成功
      statusMap[currentIP].status = isSuccess ? 'success' : 'failed';
      // 添加相应的消息
      if (isSuccess) {
        statusMap[currentIP].message = `IP ${currentIP} 部署成功`;
      } else {
        statusMap[currentIP].message = `IP ${currentIP} 部署失败，请检查网络连接`;
      }
      // 向所有客户端推送当前IP的状态更新
      this.clients.forEach(client => {
        client.send(JSON.stringify({
          cmd: cmd,
          data: {
            status: statusMap[currentIP].status,
            message: statusMap[currentIP].message
          }
        }));
      });
      // 移动到下一个IP
      currentIndex++;
      // 检查是否所有IP都已处理完毕
      if (currentIndex >= ips.length) {
        // 所有IP都已处理完，两秒后发送结束消息
        setTimeout(() => {
          this.clients.forEach(client => {
            client.send(JSON.stringify({
              cmd: cmd,
              data: {
                status: "end"
              }
            }));
          });
        }, 2000);
      } else {
        // 还有未处理的IP，两秒后处理下一个
        setTimeout(updateNextIP, 2000);
      }
    };  
    // 启动更新过程
    setTimeout(updateNextIP, 2000);
  }


  // 匹配ip推送cpu和内存数据
  public pushCpuAndMem(ips: string[]) {
     let data = []
    function getCpuAndMem(){
      return {
        cpu: Math.floor(Math.random() * 100),
        meu: Math.floor(Math.random() * 100)
      }
    }
    ips.forEach(ip=>{
        data.push({
          ipAddress:ip,
          cpu:getCpuAndMem().cpu,
          meu:getCpuAndMem().meu
        })
    })
    setInterval(()=>{
      // 每次推送时重新生成数据，保持数据的实时性
      const updatedData = ips.map(ip => ({
        ipAddress: ip,
        cpu: Math.floor(Math.random() * 100),
        meu: Math.floor(Math.random() * 100)
      }));
      
      this.clients.forEach(client => {
        client.send(JSON.stringify({
          cmd: "JRLC.get.cpu",
          data: updatedData[Math.floor(Math.random() * updatedData.length)]
        }));
      });
    }, 5000);
  }

}
